﻿using System;
using Mono.Cecil.Cil;

namespace Mono.Cecil
{
	// Token: 0x020000DC RID: 220
	internal sealed class TypeResolver
	{
		// Token: 0x060008F1 RID: 2289 RVA: 0x00026BF0 File Offset: 0x00024DF0
		public static TypeResolver For(TypeReference typeReference)
		{
			return typeReference.IsGenericInstance ? new TypeResolver((GenericInstanceType)typeReference) : new TypeResolver();
		}

		// Token: 0x060008F2 RID: 2290 RVA: 0x00026C1C File Offset: 0x00024E1C
		public static TypeResolver For(TypeReference typeReference, MethodReference methodReference)
		{
			return new TypeResolver(typeReference as GenericInstanceType, methodReference as GenericInstanceMethod);
		}

		// Token: 0x060008F3 RID: 2291 RVA: 0x00002BCC File Offset: 0x00000DCC
		public TypeResolver()
		{
		}

		// Token: 0x060008F4 RID: 2292 RVA: 0x00005468 File Offset: 0x00003668
		public TypeResolver(GenericInstanceType typeDefinitionContext)
		{
			this._typeDefinitionContext = typeDefinitionContext;
		}

		// Token: 0x060008F5 RID: 2293 RVA: 0x00005479 File Offset: 0x00003679
		public TypeResolver(GenericInstanceMethod methodDefinitionContext)
		{
			this._methodDefinitionContext = methodDefinitionContext;
		}

		// Token: 0x060008F6 RID: 2294 RVA: 0x0000548A File Offset: 0x0000368A
		public TypeResolver(GenericInstanceType typeDefinitionContext, GenericInstanceMethod methodDefinitionContext)
		{
			this._typeDefinitionContext = typeDefinitionContext;
			this._methodDefinitionContext = methodDefinitionContext;
		}

		// Token: 0x060008F7 RID: 2295 RVA: 0x00026C40 File Offset: 0x00024E40
		public MethodReference Resolve(MethodReference method)
		{
			MethodReference methodReference = method;
			bool flag = this.IsDummy();
			MethodReference result;
			if (flag)
			{
				result = methodReference;
			}
			else
			{
				TypeReference declaringType = this.Resolve(method.DeclaringType);
				GenericInstanceMethod genericInstanceMethod = method as GenericInstanceMethod;
				bool flag2 = genericInstanceMethod != null;
				if (flag2)
				{
					methodReference = new MethodReference(method.Name, method.ReturnType, declaringType);
					foreach (ParameterDefinition parameterDefinition in method.Parameters)
					{
						methodReference.Parameters.Add(new ParameterDefinition(parameterDefinition.Name, parameterDefinition.Attributes, parameterDefinition.ParameterType));
					}
					foreach (GenericParameter genericParameter in genericInstanceMethod.ElementMethod.GenericParameters)
					{
						methodReference.GenericParameters.Add(new GenericParameter(genericParameter.Name, methodReference));
					}
					methodReference.HasThis = method.HasThis;
					GenericInstanceMethod genericInstanceMethod2 = new GenericInstanceMethod(methodReference);
					foreach (TypeReference typeReference in genericInstanceMethod.GenericArguments)
					{
						genericInstanceMethod2.GenericArguments.Add(this.Resolve(typeReference));
					}
					methodReference = genericInstanceMethod2;
				}
				else
				{
					methodReference = new MethodReference(method.Name, method.ReturnType, declaringType);
					foreach (GenericParameter genericParameter2 in method.GenericParameters)
					{
						methodReference.GenericParameters.Add(new GenericParameter(genericParameter2.Name, methodReference));
					}
					foreach (ParameterDefinition parameterDefinition2 in method.Parameters)
					{
						methodReference.Parameters.Add(new ParameterDefinition(parameterDefinition2.Name, parameterDefinition2.Attributes, parameterDefinition2.ParameterType));
					}
					methodReference.HasThis = method.HasThis;
				}
				result = methodReference;
			}
			return result;
		}

		// Token: 0x060008F8 RID: 2296 RVA: 0x00026EB8 File Offset: 0x000250B8
		public FieldReference Resolve(FieldReference field)
		{
			TypeReference typeReference = this.Resolve(field.DeclaringType);
			bool flag = typeReference == field.DeclaringType;
			FieldReference result;
			if (flag)
			{
				result = field;
			}
			else
			{
				result = new FieldReference(field.Name, field.FieldType, typeReference);
			}
			return result;
		}

		// Token: 0x060008F9 RID: 2297 RVA: 0x00026EFC File Offset: 0x000250FC
		public TypeReference ResolveReturnType(MethodReference method)
		{
			return this.Resolve(GenericParameterResolver.ResolveReturnTypeIfNeeded(method));
		}

		// Token: 0x060008FA RID: 2298 RVA: 0x00026F1C File Offset: 0x0002511C
		public TypeReference ResolveParameterType(MethodReference method, ParameterReference parameter)
		{
			return this.Resolve(GenericParameterResolver.ResolveParameterTypeIfNeeded(method, parameter));
		}

		// Token: 0x060008FB RID: 2299 RVA: 0x00026F3C File Offset: 0x0002513C
		public TypeReference ResolveVariableType(MethodReference method, VariableReference variable)
		{
			return this.Resolve(GenericParameterResolver.ResolveVariableTypeIfNeeded(method, variable));
		}

		// Token: 0x060008FC RID: 2300 RVA: 0x00026F5C File Offset: 0x0002515C
		public TypeReference ResolveFieldType(FieldReference field)
		{
			return this.Resolve(GenericParameterResolver.ResolveFieldTypeIfNeeded(field));
		}

		// Token: 0x060008FD RID: 2301 RVA: 0x00026F7C File Offset: 0x0002517C
		public TypeReference Resolve(TypeReference typeReference)
		{
			return this.Resolve(typeReference, true);
		}

		// Token: 0x060008FE RID: 2302 RVA: 0x00026F98 File Offset: 0x00025198
		public TypeReference Resolve(TypeReference typeReference, bool includeTypeDefinitions)
		{
			bool flag = this.IsDummy();
			TypeReference result;
			if (flag)
			{
				result = typeReference;
			}
			else
			{
				bool flag2 = this._typeDefinitionContext != null && this._typeDefinitionContext.GenericArguments.Contains(typeReference);
				if (flag2)
				{
					result = typeReference;
				}
				else
				{
					bool flag3 = this._methodDefinitionContext != null && this._methodDefinitionContext.GenericArguments.Contains(typeReference);
					if (flag3)
					{
						result = typeReference;
					}
					else
					{
						GenericParameter genericParameter = typeReference as GenericParameter;
						bool flag4 = genericParameter != null;
						if (flag4)
						{
							bool flag5 = this._typeDefinitionContext != null && this._typeDefinitionContext.GenericArguments.Contains(genericParameter);
							if (flag5)
							{
								result = genericParameter;
							}
							else
							{
								bool flag6 = this._methodDefinitionContext != null && this._methodDefinitionContext.GenericArguments.Contains(genericParameter);
								if (flag6)
								{
									result = genericParameter;
								}
								else
								{
									result = this.ResolveGenericParameter(genericParameter);
								}
							}
						}
						else
						{
							ArrayType arrayType = typeReference as ArrayType;
							bool flag7 = arrayType != null;
							if (flag7)
							{
								result = new ArrayType(this.Resolve(arrayType.ElementType), arrayType.Rank);
							}
							else
							{
								PointerType pointerType = typeReference as PointerType;
								bool flag8 = pointerType != null;
								if (flag8)
								{
									result = new PointerType(this.Resolve(pointerType.ElementType));
								}
								else
								{
									ByReferenceType byReferenceType = typeReference as ByReferenceType;
									bool flag9 = byReferenceType != null;
									if (flag9)
									{
										result = new ByReferenceType(this.Resolve(byReferenceType.ElementType));
									}
									else
									{
										PinnedType pinnedType = typeReference as PinnedType;
										bool flag10 = pinnedType != null;
										if (flag10)
										{
											result = new PinnedType(this.Resolve(pinnedType.ElementType));
										}
										else
										{
											GenericInstanceType genericInstanceType = typeReference as GenericInstanceType;
											bool flag11 = genericInstanceType != null;
											if (flag11)
											{
												GenericInstanceType genericInstanceType2 = new GenericInstanceType(genericInstanceType.ElementType);
												foreach (TypeReference typeReference2 in genericInstanceType.GenericArguments)
												{
													genericInstanceType2.GenericArguments.Add(this.Resolve(typeReference2));
												}
												result = genericInstanceType2;
											}
											else
											{
												RequiredModifierType requiredModifierType = typeReference as RequiredModifierType;
												bool flag12 = requiredModifierType != null;
												if (flag12)
												{
													result = this.Resolve(requiredModifierType.ElementType, includeTypeDefinitions);
												}
												else
												{
													if (includeTypeDefinitions)
													{
														TypeDefinition typeDefinition = typeReference as TypeDefinition;
														bool flag13 = typeDefinition != null && typeDefinition.HasGenericParameters;
														if (flag13)
														{
															GenericInstanceType genericInstanceType3 = new GenericInstanceType(typeDefinition);
															foreach (GenericParameter typeReference3 in typeDefinition.GenericParameters)
															{
																genericInstanceType3.GenericArguments.Add(this.Resolve(typeReference3));
															}
															return genericInstanceType3;
														}
													}
													bool flag14 = typeReference is TypeSpecification;
													if (flag14)
													{
														throw new NotSupportedException(string.Format("The type {0} cannot be resolved correctly.", typeReference.FullName));
													}
													result = typeReference;
												}
											}
										}
									}
								}
							}
						}
					}
				}
			}
			return result;
		}

		// Token: 0x060008FF RID: 2303 RVA: 0x00027294 File Offset: 0x00025494
		internal TypeResolver Nested(GenericInstanceMethod genericInstanceMethod)
		{
			return new TypeResolver(this._typeDefinitionContext as GenericInstanceType, genericInstanceMethod);
		}

		// Token: 0x06000900 RID: 2304 RVA: 0x000272B8 File Offset: 0x000254B8
		private TypeReference ResolveGenericParameter(GenericParameter genericParameter)
		{
			bool flag = genericParameter.Owner == null;
			TypeReference result;
			if (flag)
			{
				result = this.HandleOwnerlessInvalidILCode(genericParameter);
			}
			else
			{
				MemberReference memberReference = genericParameter.Owner as MemberReference;
				bool flag2 = memberReference == null;
				if (flag2)
				{
					throw new NotSupportedException();
				}
				result = ((genericParameter.Type == GenericParameterType.Type) ? this._typeDefinitionContext.GenericArguments[genericParameter.Position] : ((this._methodDefinitionContext != null) ? this._methodDefinitionContext.GenericArguments[genericParameter.Position] : genericParameter));
			}
			return result;
		}

		// Token: 0x06000901 RID: 2305 RVA: 0x0002733C File Offset: 0x0002553C
		private TypeReference HandleOwnerlessInvalidILCode(GenericParameter genericParameter)
		{
			bool flag = genericParameter.Type == GenericParameterType.Method && this._typeDefinitionContext != null && genericParameter.Position < this._typeDefinitionContext.GenericArguments.Count;
			TypeReference result;
			if (flag)
			{
				result = this._typeDefinitionContext.GenericArguments[genericParameter.Position];
			}
			else
			{
				result = genericParameter.Module.TypeSystem.Object;
			}
			return result;
		}

		// Token: 0x06000902 RID: 2306 RVA: 0x000273AC File Offset: 0x000255AC
		private bool IsDummy()
		{
			return this._typeDefinitionContext == null && this._methodDefinitionContext == null;
		}

		// Token: 0x04000376 RID: 886
		private readonly IGenericInstance _typeDefinitionContext;

		// Token: 0x04000377 RID: 887
		private readonly IGenericInstance _methodDefinitionContext;
	}
}
